<?php
// +----------------------------------------------------------------------
// | [ WE ONLY DO WHAT IS NECESSARY ]
// +----------------------------------------------------------------------
// | Author < 931274989@qq.com >
// +----------------------------------------------------------------------
// | Explain 
// +----------------------------------------------------------------------
namespace app\api\service;

use app\api\service\Order as orderService;
use EasyWeChat\Foundation\Application;
use app\lib\exception\TokenException;
use app\lib\exception\OrderException;
use app\model\Order as orderModel;
use app\lib\enum\OrderStatusEnum;
use EasyWeChat\Payment\Order;
use think\facade\Log;
use think\Exception;

class Pay
{
  private $orderID;
  private $orderNO;

  function __construct($orderID)
  {
    if(!$orderID) {
      throw new Exception('订单号不允许为空');
    }
    $this->orderID = $orderID;
  }

  // 支付主体方法
  public function pay()
  {
    // 订单号可能根本不存在
    // 订单号存在，但是订单号和当前用户不匹配
    // 订单可能已经被支付过了
    // 库存量检测
    $this->checkOrderValid();
    $orderService = new orderService();
    $status = $orderService->checkOrderStock($this->orderID);
    if (!$status['pass']) {
      return $status;
    }
    return $this->makeWxPreOrder($status['orderPrice']);
  }

  // 发送微信预订单请求
  private function makeWxPreOrder($totalPrice)
  {
    $openid = Token::getCurrentTokenVar('openid');
    if(!$openid) {
      throw new TokenException();
    }
    // 微信支付参数
    $product = [
      'trade_type'       => 'JSAPI', // 微信公众号支付填JSAPI
      'body'             => '零食商贩', // 商品简要描述
      'out_trade_no'     => $this->orderNO, // 订单号
      'total_fee'        => $totalPrice*100, // 金额 单位：分
      'openid'           => $openid, // trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识，
      'notify_url'       => url(config('secure.pay_back_url')), // 支付结果通知网址，如果不设置则会使用配置里的默认地址
      // ...
    ];
    $wxOrderData = new Order($product);
    return $this->getPaySignature($wxOrderData);
  }

  // 调用微信支付
  private function getPaySignature($wxOrderData)
  {
    $options = config('wx.wxConfig');
    $app = new Application($options);
    $payment = $app->payment;
    $wxOrder = $payment->prepare($wxOrderData); // 这里的order是上面一步得来的。 这个prepare()帮你计算了校验码，帮你获取了prepareId.省心。
    $prepayId = null;
    if ($wxOrder->return_code != 'SUCCESS' || $wxOrder->result_code != 'SUCCESS'){
      Log::record($wxOrder,'error');
      Log::record('获取预支付订单失败','error');
    }
    $this->recordPreOrder($wxOrder);
    // 生成支付签名参数
    $prepayId = $wxOrder->prepay_id; // 这个很重要。有了这个才能调用支付。 
    $sign = $payment->configForPayment($prepayId);
    $signature = json_decode($sign,true);  
    unset($signature['appId']);
    return $signature;
  }

  // 处理微信返回结果
  private function recordPreOrder($wxOrder)
  {
    orderModel::where('id','=',$this->orderID)->update(['prepay_id'=>$wxOrder->prepay_id]);
  }

  // 检测订单
  private function checkOrderValid()
  {
    // 检测订单号是否存在
    $order = orderModel::where('id','=',$this->orderID)->find();
    if (!$order) {
      throw new OrderException();
    }
    // 检测订单号和当前用户是否匹配
    if (!Token::isValidOperate($order->user_id)) {
      throw new TokenException([
        'msg' => '订单与用户不匹配',
        'errorCode' => 10003
      ]);
    }
    // 检测订单是否已经被支付过了
    if ($order->status != OrderStatusEnum::UNPAID) {
      throw new OrderException([
        'msg' => '订单已经被支付过啦',
        'errorCode' => 80003,
        'code' => 400
      ]);
    }
    $this->orderNO = $order->order_no;
    return true;
  }
}
?>